#include <thread>
#include <atomic>
#include <condition_variable>
#include <vector>
#include <deque>

#ifndef ThreadPool_H_
#define ThreadPool_H_

namespace ThreadPool {

class ThreadPool;

/**
 * Base class for your Task , Derive you worker class from this class
 * and implement run() method
 */
class WorkerTask {
public:
  WorkerTask(){}
  virtual void run(){}
};

typedef std::unique_ptr<WorkerTask> TaskPtr;

class WorkerThread {
public:
  WorkerThread(ThreadPool& tPool);
  void operator()();

private:
  std::string _threadID;
  ThreadPool& _threadPool;

};

class ThreadPool {
private:
  friend class WorkerThread;
  std::vector<std::thread> _threadColl;
  std::deque<TaskPtr>      _taskQueue;


  std::atomic<bool>        _timeToExit;
  std::mutex               _queueLock;
  std::condition_variable  _condition;



public :
  ThreadPool(unsigned int maxThreads);
  ~ThreadPool();

  bool exit() {
    return _timeToExit.load();
  }

  void addTask(TaskPtr ptr);

  bool queueEmpty();

  TaskPtr getNextTask();

  void waitForWorkers();

};


}

#endif//ThreadPool_H_
